# -*- coding;utf-8 -*-
"""
File name : WriteQuestionList2Tex.py.PY
Program IDE : PyCharm
Create file time: 2025/1/2 11:09
File Create By Author : 朱清闯
"""
import requests
from jinja2 import Template
import os
from django.conf import settings
import re
from html.parser import HTMLParser
import pypandoc
from utils import Html2Pdf


def delete_string(content_str):
    pattern_list = [(r'</p><p>', ' <br> '),
                    (r'</p><table', ' <br> <table '),
                    (r'</p><img', ' <br> <img'),
                    (r'</p>', r' <br> '),
                    (r'<p>', r''),
                    # (r'$\underline{\quad\quad}$', r'____'),
                    ]
    target1 = r"$\underline{\quad\quad}$"
    if target1 in content_str:
        content_str = content_str.replace(target1, "___")
    target2 = r"\underline{\quad\quad}$"
    if target2 in content_str:
        content_str = content_str.replace(target2, "$___")
    for item in pattern_list:
        content_str = re.sub(item[0], item[1], content_str)
    return content_str


# 把一般的html符号转换成实际符号
def convert_html_tags_to_markdown(content_str):
    pattern_list = [(r'&lt;', '<'),
                    (r'&gt;', '>'),
                    (r'&amp;', '&'),
                    (r'&quot;', r'”'),
                    (r'&times;', '×'),
                    (r'&divide;', '÷'),
                    (r'</p><p>', ' \n \n '),
                    (r'</p><table', '\n\n<table '),
                    (r'</p><img', '\n\n<img'),
                    (r'</p>', r' \n \n '),
                    (r'<p>', r''),
                    ]
    for item in pattern_list:
        content_str = re.sub(item[0], item[1], content_str)
    return content_str


# 从html表格中提取内容，返回二维数组
class TableParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.in_table = False
        self.in_tr = False
        self.in_td = False
        self.in_th = False
        self.rows = []
        self.current_row = []
        self.current_data = ''

    def handle_starttag(self, tag, attrs):
        if tag == 'table':
            self.in_table = True
        elif tag == 'tr' and self.in_table:
            self.in_tr = True
            # 开始新的行时，如果当前行有数据，则将其添加到rows中
            if self.current_row:
                self.rows.append(self.current_row)
                self.current_row = []
        elif (tag == 'td' or tag == 'th') and self.in_tr:
            self.in_td = True

    def handle_endtag(self, tag):
        if tag == 'table':
            self.in_table = False
        elif tag == 'tr':
            self.in_tr = False
            # 结束行时，将当前行添加到rows中
            if self.current_row:
                self.rows.append(self.current_row)
                self.current_row = []
        elif tag == 'td' or tag == 'th':
            self.in_td = False
            self.in_th = False
            # 结束单元格时，将当前数据添加到当前行中
            if self.current_data.strip():
                self.current_row.append(self.current_data.strip())
            self.current_data = ''

    def handle_data(self, data):
        if self.in_td:
            self.current_data += data


def extract_table_data(html):
    rows = html.split('<tr>')
    data = []
    for row in rows[1:]:
        if '<td>' in row:
            cells = row.split('<td>')[1:]
        else:
            cells = row.split('<th>')[1:]
        row_data = []
        for cell in cells:
            if '</td>' in cell:
                content = cell.split('</td>')[0]
            else:
                content = cell.split('</th>')[0]
            row_data.append(content)
        data.append(row_data)
    return data


# 把表格转行成latex格式
def table_to_markdown(string: str):
    if 'table' not in string:
        return string
    table_data = extract_table_data(string)
    print('二维数组的表格', table_data)
    align_symbol = '| ------ ' * len(table_data[0]) + '|\n'
    table_markdown = ''
    row_index = 0
    for row_item in table_data:
        col_item = "|"
        for col_index in range(len(row_item)):
            col_item += ' ' + row_item[col_index] + ' |'
        table_markdown += col_item + '\n'
        if row_index == 0:
            table_markdown += align_symbol
        row_index += 1
    table_markdown += '\n\n'
    print('转换后的markdown表格：', table_markdown)
    return table_markdown


# 把表格转行成markdown格式
def convert_table_tags_to_markdown(string: str):
    i = 0
    match = re.search(r'<table.*?</table>', string[i:])
    i = string.find(r'<table')
    while match:
        table_str = match.group(0)
        table_markdown = table_to_markdown(string=table_str)
        string = string[:i] + table_markdown + string[i+len(table_str):]
        i = string.find(r'<table')
        match = re.search(r'<table.*?</table>', string[i:])
    return string


# 把图片转行成latex格式
def convert_image_tags_to_markdown(string: str, question_type=1):
    i = 0
    match_static = re.search(r'/static/images/(.*?)\"', string[i:])
    match_img = re.search(r'<img.*?>', string[i:])
    i = string.find(r'<img')
    while match_static:
        # 注意去掉尾部的双引号
        image_name = '/data/djangoStatic-czsx' + match_static.group(0)[:-1]
        if question_type == 3:
            # 非选择题保持原图片大小
            graphic_string = r'![](' + image_name + r')'
        elif question_type == 2:
            graphic_string = r'![](' + image_name + r')'
        elif question_type == 1:
            # 选项内的图片控制在宽度1.5cm，非选项内，控制3cm
            if 'A.' in string[i-5:i] or 'B.' in string[i-5:i] or 'C.' in string[i-5:i] or 'D.' in string[i-5:i]:
                graphic_string = r'![](' + image_name + r'){width=100}'
            else:
                graphic_string = r'![](' + image_name + r')'
        string = string[:i] + graphic_string + string[i+len(match_img.group(0)):]
        i = string.find(r'<img')
        match_img = re.search(r'<img.*?>', string[i:])
        match_static = re.search(r'/static/images/(.*?)\"', string[i:])
    return string


def replace_placeholder_in_html(paper_information: dict, question_list: list, liti_list: list, lianxi_list: list):
    data = {'zsd': paper_information['zsd'], 'paper_title': paper_information['title'], 'question_list': question_list,
            'liti_list': liti_list, 'lianxi_list': lianxi_list}
    file_path = os.path.join(settings.BASE_DIR).replace('\\', '/') + "/static/temp/templates/template_exercise.html"
    if paper_information['usage_type'] == 'examination':
        file_path = os.path.join(settings.BASE_DIR).replace('\\', '/') + "/static/temp/templates/template_examination" \
                                                                         ".html"
    elif paper_information['usage_type'] == 'guidepaper':
        file_path = os.path.join(settings.BASE_DIR).replace('\\',
                                                            '/') + "/static/temp/templates/template_guidepaper.html"
    with open(file_path, 'r', encoding='utf-8') as file:
        content = file.read()
        template = Template(content)
        new_content = template.render(data)
    file_path_new = os.path.join(settings.BASE_DIR).replace('\\', '/') + '/static/temp/html/a.html'
    with open(file_path_new, 'w', encoding='utf-8') as file:
        file.write(new_content)
    print("占位符已成功替换。")


# 只要图片和需要图书处理，顺便添加题号，并且处理二维码图片
def deal_image(question_list):
    for i in range(len(question_list)):
        question_list[i]['content'] = delete_string(str(i+1) + '. ' + question_list[i]['content'])
        question_list[i]['answer'] = delete_string(str(i+1) + '. 【答案】' + question_list[i]['answer'])
        question_list[i]['explain'] = delete_string('【解析】' + question_list[i]['explain'])
        if question_list[i]['qr_code_url'] != '':
            question_list[i]['qr_code_url'] = '<img src="' + question_list[i]['qr_code_url'] + '" width="80" height="80" >'
    return question_list


# 处理换行、图片、表格的格式
def deal_tail_newline_and_convert_image_table(question_list):
    for i in range(len(question_list)):
        question_list[i]['content'] = convert_html_tags_to_markdown(str(i+1) + '. ' + question_list[i]['content'])
        len_newline = -len('<br>')
        if '<br>' in question_list[i]['content'].strip()[-6:]:
            # print(f'第{i}个content尾部含有换行')
            question_list[i]['content'] = question_list[i]['content'].strip()[:len_newline]
        question_list[i]['answer'] = convert_html_tags_to_markdown(str(i+1) + '. 【答案】' + question_list[i]['answer'])
        if '<br>' in question_list[i]['answer'].strip()[-5:]:
            question_list[i]['answer'] = question_list[i]['answer'].strip()[:len_newline]
        question_list[i]['explain'] = convert_html_tags_to_markdown(question_list[i]['explain'])
        if '<br>' in question_list[i]['explain'].strip()[-5:]:
            question_list[i]['explain'] = question_list[i]['explain'].strip()[:len_newline]
        question_list[i]['content'] = convert_image_tags_to_markdown(question_list[i]['content'])
        question_list[i]['answer'] = convert_image_tags_to_markdown(question_list[i]['answer'])
        question_list[i]['explain'] = convert_image_tags_to_markdown(question_list[i]['explain'])
        question_list[i]['content'] = convert_table_tags_to_markdown(question_list[i]['content'])
        question_list[i]['answer'] = convert_table_tags_to_markdown(question_list[i]['answer'])
        question_list[i]['explain'] = convert_table_tags_to_markdown(question_list[i]['explain'])
    print('转换成markdown后的question_list内容：', question_list)
    return question_list


def write_questions_2_html(paper_information=None, question_list=None):
    print('进入html渲染, 原始试题:', question_list)
    # 把html元素转换成latex格式，去掉尾部的换行符newline
    if paper_information is None:
        paper_information = {'title': '浙江省信息技术选考模拟', 'answer_position': 'detach', 'type_sorted': False,
                             'return_file_type': 'docx', 'usage_type': 'exercise', 'liti_list': [], 'lianxi_list': []}
    liti_list = paper_information['liti_list']
    lianxi_list = paper_information['lianxi_list']
    # 练习卷和测试卷都用question_list数组，进行转换处理
    if paper_information['usage_type'] in ['exercise', 'examination']:
        question_list = deal_image(question_list)
    # 导学案都用liti_list和lianxi_list数组，进行转换处理
    else:
        liti_list = deal_image(paper_information['liti_list'])
        lianxi_list = deal_image(paper_information['lianxi_list'])
    print('处理后的试题：', question_list)
    # 把试题和试卷信息写入文件a.md，利用jinja2写入模板得到a.md
    replace_placeholder_in_html(paper_information=paper_information, question_list=question_list, liti_list=liti_list,
                                lianxi_list=lianxi_list)
    # 读取并发送 a.md 文件流给flask端
    tex_file_path = os.path.join(settings.BASE_DIR).replace('\\', '/') + "/static/temp/html/a.html"
    if not os.path.exists(tex_file_path):
        print('/static/temp/html/a.html不存在')
        return 'error'
    # 文件流并保存到/static/temp/html/目录下

    extension = 'docx'
    if paper_information['return_file_type'] == 'pdf_local':
        extension = 'pdf'
    return_file_path = os.path.join(settings.BASE_DIR).replace('\\', '/') + f"/static/temp/html/a.{extension}"
    if extension == 'docx':
        pypandoc.convert_file(source_file=tex_file_path, to=extension, format='html+tex_math_dollars', outputfile=return_file_path)
    else:
        success = Html2Pdf.html_to_pdf_with_formulas(html_file_path=tex_file_path, output_pdf_path=return_file_path)
        if not success:
            return 'error'
    return f"/static/temp/html/a.{extension}"
    # 以下是发给京东服务器处理，利用texlive结合pandco，较为麻烦
    # with open(tex_file_path, 'rb') as tex_file:
    #     tex_file_content = tex_file.read()
    #     url = "http://117.72.37.184:5000/markdown2docx"
    #     headers = {'Content-Type': 'application/octet-stream', 'Return-File-Type': paper_information['return_file_type'],
    #                'File-Type': file_type}
    #     response = requests.post(url, data=tex_file_content, headers=headers)
    #     print('收到flask端发来的结果：', response)
    #     if response.status_code == 200:
    #         # 以文件流形式发送给前端
    #         with open(return_file_path, 'wb') as pdf_file:
    #             pdf_file.write(response.content)
    #         return f"/static/temp/html/a.docx"
    #     return 'error'
